package com.shen.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;


import static com.shen.constant.GeoConstant.*;


/**
 * 高德地图工具类
 */
@Slf4j
public class GaoDeMapUtil {


    private GaoDeMapUtil() {
    }

    /**
     * 根据机构名称获取对应的地理信息
     *
     * @param jgmc 机构名称
     * @return 地理信息
     */
    public static String[] getGeoInfos(String jgmc) {
        String requestUrl = String.format(GAO_DE_URL, API_KEY, XIN_JIANG_CITY, jgmc);
        String responseStr = sendRequest(requestUrl);
        return handleResponse(responseStr, jgmc);
    }


    /**
     * 向高德的api发送请求
     *
     * @param serverUrl 请求url
     * @return 响应字符串
     */
    private static String sendRequest(String serverUrl) {
        StringBuilder result = new StringBuilder();
        try {
            URL url = new URL(serverUrl);
            URLConnection conn = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            in.close();
        } catch (Exception e) {
            log.error("[请求高德API] 请求异常:", e);
        }
        return result.toString();
    }

    /**
     * 处理响应字符串，提取地理信息到数组中
     *
     * @param responseStr 响应字符串
     * @param jgmc        机构名称
     * @return 地理信息数组
     */
    private static String[] handleResponse(String responseStr, String jgmc) {
        String[] geoInfos = new String[NUM_8];
        geoInfos[NUM_0] = jgmc;
        if (!StringUtils.hasLength(responseStr)) {
            log.warn("[请求高德API] 响应值为空");
            return geoInfos;
        }
        try {
            JSONObject responseObject = JSON.parseObject(responseStr);
            String responseStatus = responseObject.getString(STATUS);
            if (!SUCCESS_STATUS.equals(responseStatus)) {
                log.error("[请求高德API] 请求状态值为异常:{}", responseObject.get(INFO));
                return geoInfos;
            }
            JSONArray geocodes = responseObject.getJSONArray(GEOCODES);
            //只取JSONArray的第一个元素，即第一个最匹配的地址
            JSONObject geocode = (JSONObject) geocodes.get(NUM_0);
            handleGeoCode(geocode, geoInfos);
            return geoInfos;
        } catch (Exception e) {
            log.error("[请求高德API] 处理响应异常:", e);
        }
        return geoInfos;
    }

    /**
     * 处理响应体中地理编码信息列表
     *
     * @param geocode  地理编码信息列表
     * @param geoInfos 地理信息数组
     */
    private static void handleGeoCode(JSONObject geocode, String[] geoInfos) {
        geoInfos[NUM_1] = geocode.getString(FORMATTED_ADDRESS);
        String location = geocode.getString(LOCATION);
        if (StringUtils.hasText(location)) {
            String[] jw = location.split(COMMA);
            geoInfos[NUM_2] = jw[NUM_0];
            geoInfos[NUM_3] = jw[NUM_1];
        }
        isNotBlankHandleGeoInfo(geocode, geoInfos, NUM_4, ADCODE);
        isNotBlankHandleGeoInfo(geocode, geoInfos, NUM_5, PROVINCE);
        isNotBlankHandleGeoInfo(geocode, geoInfos, NUM_6, CITY);
        isNotBlankHandleGeoInfo(geocode, geoInfos, NUM_7, DISTRICT);
    }

    /**
     * 对于地理信息编码信息列表进行非空判断，不为空则赋值到数组中
     *
     * @param geocode  地理编码信息列表
     * @param geoInfos 地理信息数组
     * @param num      索引
     * @param keyName  键名
     */
    private static void isNotBlankHandleGeoInfo(JSONObject geocode, String[] geoInfos, int num, String keyName) {
        String value = geocode.getString(keyName);
        if (StringUtils.hasText(value)) {
            geoInfos[num] = value;
        }
    }

}
